package com.aispeech.audiowavelib.draw;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
import android.view.SurfaceView;

import com.aispeech.audiowavelib.view.WaveSurfaceView;

import java.util.LinkedList;

public class WaveCanvas {

    private final String TAG = "WaveCanvas";
    private LinkedList<Short> inBuf;

    private static final int SAMPLE_RATE = 16000;//默认采样16k
    private int lineOff;//上下边距的距离
    private int rateX = 800;//控制多少帧取一帧
    private int rateY = 1; //  Y轴缩小的比例 默认为1
    public int baseLine = 0;// Y轴基线

    private int marginRight = 130;//波形图绘制距离右边的距离
    private int marginLeft = 20;//波形图绘制距离左边的距离
    private float drawTime = 20.00f;//多长时间画满一个通道(mSfv.getWidth() - marginRight - marginLeft),单位秒

    private float divider = 0.01f;//为了节约绘画时间，默认每100个数据画一次,实际上根据rateX来订

    private Paint circlePaint;
    private Paint center;
    private Paint paintLine;
    private Paint mPaint;  //画笔
    private SurfaceView mSfv;// 画板

    private Handler drawHandler;//用来将draw操作放到drawThread线程,保证不要阻塞录音回调.
    private static HandlerThread drawThread;

    private final int MSG_START_DRAW = 1;
    private final int MSG_STOP = 2;

    //    private boolean currentChannelDataValidity = false;//当前通道录音数据是否有效
    public enum BG_COLOR {
        WHITE, PINK
    }

    private BG_COLOR mCurrentBgColor = BG_COLOR.WHITE;

    public WaveCanvas() {
//        init(sfv);
        drawThread = new HandlerThread("drawWaveThread");
        drawThread.start();
        //获取主线程handler
        drawHandler = new Handler(drawThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);

                switch (msg.what) {
                    case MSG_START_DRAW:
                        LinkedList<Short> cpbuf;
                        synchronized (WaveCanvas.this) {
                            cpbuf = (LinkedList<Short>) inBuf.clone();
                        }

                        Canvas canvasc = mSfv.getHolder().lockCanvas(
                            new Rect(0, 0, mSfv.getWidth(), mSfv.getHeight()));// 关键:获取画布
                        if (canvasc == null) {
                            Log.e(TAG, "simpleDraw: canvas is null !");
                            drawHandler.removeMessages(MSG_START_DRAW);
                            return;
                        }

                        //用于清掉之前的current line
                        drawCanvasBgColor(mCurrentBgColor, canvasc);

                        float y;
                        int start = (int) ((cpbuf.size()) * divider);
                        int height = mSfv.getHeight() - lineOff;

                        if (mSfv.getWidth() - start <= marginRight) {//如果超过预留的右边距距离
                            start = mSfv.getWidth() - marginRight;//画的位置x坐标
                        }
                        canvasc.drawLine(0, lineOff / 2, mSfv.getWidth(), lineOff / 2, paintLine);//最上面的那根线
                        canvasc.drawLine(0, mSfv.getHeight() - lineOff / 2 - 1, mSfv.getWidth(), mSfv.getHeight() - lineOff / 2 - 1, paintLine);//最下面的那根线
                        canvasc.drawCircle(start, lineOff / 2, lineOff / 10, circlePaint);// 上圆
                        canvasc.drawCircle(start, mSfv.getHeight() - lineOff / 2 - 1, lineOff / 10, circlePaint);// 下圆
                        canvasc.drawLine(start, lineOff / 2, start, mSfv.getHeight() - lineOff / 2, circlePaint);//垂直的线
                        canvasc.drawLine(0, height * 0.5f + lineOff / 2, mSfv.getWidth(), height * 0.5f + lineOff / 2, center);//中心线

                        for (int i = 0; i < cpbuf.size(); i++) {
                            short data = cpbuf.get(i);
                            if (cpbuf.size() > ((mSfv.getWidth() - marginRight) / divider)) {
                                data = cpbuf.pollFirst();
                                i = 0;
                            }

                            y = data / rateY + baseLine;// 调节缩小比例，调节基准线
                            float x = (i) * divider;
                            if (mSfv.getWidth() - (i - 1) * divider <= marginRight) {
                                x = mSfv.getWidth() - marginRight;
                            }
                            //画线的方式很多，你可以根据自己要求去画。这里只是为了简单
                            float y1 = mSfv.getHeight() - y;
                            if (y < lineOff / 2) {
                                y = lineOff / 2;
                            }
                            if (y > mSfv.getHeight() - lineOff / 2 - 1) {
                                y = mSfv.getHeight() - lineOff / 2 - 1;

                            }
                            if (y1 < lineOff / 2) {
                                y1 = lineOff / 2;
                            }
                            if (y1 > (mSfv.getHeight() - lineOff / 2 - 1)) {
                                y1 = (mSfv.getHeight() - lineOff / 2 - 1);
                            }
                            canvasc.drawLine(x, y, x, y1, mPaint);//中间出波形
                        }

                        mSfv.getHolder().unlockCanvasAndPost(canvasc);// 解锁画布，提交画好的图像
                        break;
                    case MSG_STOP:
                        inBuf.clear();

                        Canvas canClean = mSfv.getHolder().lockCanvas(
                            new Rect(0, 0, mSfv.getWidth(), mSfv.getHeight()));// 关键:获取画布
                        if (canClean == null) {
                            Log.e(TAG, "simpleDraw: canvas is null !");
                            return;
                        }
//                        mCurrentBgColor = BG_COLOR.WHITE;
//                        canClean.drawARGB(255, 239, 239, 239);
                        drawCanvasBgColor(BG_COLOR.WHITE, canClean);
                        int h = mSfv.getHeight() - lineOff;

                        canClean.drawLine(0, lineOff / 2, mSfv.getWidth(), lineOff / 2, paintLine);//最上面的那根线
                        canClean.drawLine(0, mSfv.getHeight() - lineOff / 2 - 1, mSfv.getWidth(), mSfv.getHeight() - lineOff / 2 - 1, paintLine);//最下面的那根线
                        canClean.drawCircle(0, lineOff / 2, lineOff / 10, circlePaint);// 上圆
                        canClean.drawCircle(0, mSfv.getHeight() - lineOff / 2 - 1, lineOff / 10, circlePaint);// 下圆
                        canClean.drawLine(0, lineOff / 2, 0, mSfv.getHeight() - lineOff / 2, circlePaint);//垂直的线
                        canClean.drawLine(0, h * 0.5f + lineOff / 2, mSfv.getWidth(), h * 0.5f + lineOff / 2, center);//中心线

                        mSfv.getHolder().unlockCanvasAndPost(canClean);// 解锁画布，提交画好的图像

                        break;
                }
            }
        };
    }

    private void drawCanvasBgColor(BG_COLOR bgColor, Canvas canvas) {
        switch (bgColor) {
            case PINK:
                canvas.drawARGB(255, 239, 174, 185);
                break;
            case WHITE:
                canvas.drawARGB(255, 239, 239, 239);
                break;
        }
    }

    /**
     * @param sfv SurfaceView //     * @param interval 每个buf所占录音时长,与Record read 时传入的buffer大小关联
     */
    public void init(SurfaceView sfv) {

        baseLine = sfv.getHeight() / 2;
        Log.d(TAG, "init: baseLine = " + baseLine);

        circlePaint = new Paint();//画圆
        circlePaint.setColor(Color.rgb(246, 131, 126));//设置上圆的颜色

        center = new Paint();//中心线
        center.setColor(Color.rgb(39, 199, 175));// 画笔为color
        center.setStrokeWidth(1);// 设置画笔粗细
        center.setAntiAlias(true);
        center.setFilterBitmap(true);
        center.setStyle(Style.FILL);

        paintLine = new Paint();
        paintLine.setColor(Color.rgb(221, 221, 221));

        mPaint = new Paint();
        mPaint.setColor(Color.rgb(39, 199, 175));// 画笔为color
        mPaint.setStrokeWidth(1);// 设置画笔粗细
        mPaint.setAntiAlias(true);
        mPaint.setFilterBitmap(true);
        mPaint.setStyle(Style.FILL);

        mSfv = sfv;

        lineOff = ((WaveSurfaceView) sfv).getLineOff();

        inBuf = new LinkedList<>();
    }

    public void stopDraw() {
        Log.d(TAG, "stopDraw: ");
        if (null != drawHandler) {
            drawHandler.removeMessages(MSG_START_DRAW);
            drawHandler.sendEmptyMessage(MSG_STOP);
        }
    }

    public void setBackGround(BG_COLOR bgColor) {
        Log.d(TAG, "setBackGround with: bgColor = " + bgColor + "");
        mCurrentBgColor = bgColor;
    }

    public void destroy() {
        Log.d(TAG, "destroy: ");
        if (null != inBuf) {
            inBuf = null;
        }
        if (null != drawThread) {
            drawThread.quit();
            drawThread = null;
        }
        if (null != drawHandler) {
            drawHandler.getLooper().quit();
            drawHandler = null;
        }
    }

    /**
     * 绘制指定区域
     *
     * @param buf 录音数据
     */
    public void startDraw(byte[] buf) {
        if (null == buf || buf.length == 0) {
            Log.e(TAG, "simpleDraw: buf is invalid !");
            return;
        }
        for (int i = 0; i < buf.length - 1; i += rateX) {
            synchronized (this) {
                short data = get16bitData(buf[i], buf[i + 1]);
                inBuf.add(data);
            }
        }

        divider = (mSfv.getWidth() - marginRight - marginLeft) / (SAMPLE_RATE * drawTime / rateX);
        rateY = (65535 / 2 / (mSfv.getHeight() - lineOff));//65535 = 0xffff

        drawHandler.sendEmptyMessage(MSG_START_DRAW);
    }

    //每个byte占8位,所以每个点的音频按16bit采集的话,需要两个byte拼接成一个short来表示
    private short get16bitData(byte low, byte high) {
        short intValue = (short) (low & 0x00FF);
        intValue += (high & 0xFF) << 8;
        return intValue;
    }
}
